#include "stdafx.h"
#include "FilesRefactorUtils.h"

FilesRefactor::FilesRefactor(void (*pReportProgressFunc)(void* pt2Object, int progress, bool closeProgressWindow),
							 int (*pFrogMessageBoxFunc)(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType),
							 void* callbackObject)
:
FilerFrogElement(NULL),
m_ReportProgressFunc(pReportProgressFunc),
m_CallbackObject(callbackObject)
{
	FilesRefactorUtils::s_FrogMessageBoxFunc = pFrogMessageBoxFunc;
}

FilesRefactor::~FilesRefactor()
{
}

void FilesRefactor::SetParentWindow(HWND parent)
{
	m_parent = parent;
}

void FilesRefactor::ReportProgress(int progress, bool closeProgressWindow)
{
	if (m_ReportProgressFunc != NULL)
	{
		m_ReportProgressFunc(m_CallbackObject, progress, closeProgressWindow);
	}
}

/************************************/
/* File Organizing Methods			*/
/************************************/

void FilesRefactor::ExtractFilesFromMultipleFolders(FRRESPONSE& res, std::list<wstring> &foldersPaths)
{
	int success = 0;

	for (list<wstring>::const_iterator iter=foldersPaths.begin(); iter!=foldersPaths.end(); iter++)
	{		
		ExtractFilesFromFolder(res, *iter);

		if (res.Kind != SUCCESS)
		{
			if (res.Kind == FAIL_UNEXPECTED_ERROR)
			{
				return;
			}			
		}
		else
		{
			success++;
		}
	}	

	if (success == (int)foldersPaths.size())
	{
		FilesRefactorUtils::FillResponse(res, SUCCESS, EXTRACT_FROM_FOLDER, L"", success, 0);
	}
	else
	{
		WCHAR str[10];
		_itow_s((foldersPaths.size() - success), str, 10, 10);
		wstring msg(str + wstring(L" folders failed to extract.\n\n(Are some of the files open?!)"));

		FilesRefactorUtils::FillResponse(res, FAIL_SOME_FILES_FAILED, EXTRACT_FROM_FOLDER, msg.c_str(), success, (foldersPaths.size() - success));
	}
}

void FilesRefactor::ExtractFilesFromFolder(FRRESPONSE& res, const wstring& folderPath)
{
	// Check if path exists
	if (!PathFileExists(folderPath.c_str()))
	{
		wcout << L"FilesRefactor::ExtractFilesFromFolder: Folder dosen't exist!" << endl;

		FilesRefactorUtils::FillResponse(res, FAIL_DIRECTORY_DOESNT_EXIST, EXTRACT_FROM_FOLDER, L"The given folder dosen't exist.", 1, 0);
		return;
	}

	FileMachine fm(m_parent, folderPath);

	if (fm.IsFile())
	{
		wcout << L"FilesRefactor::ExtractFilesFromFolder: a file was selected!" << endl;

		FilesRefactorUtils::FillResponse(res, FAIL_IS_FILE_NOT_DIR, EXTRACT_FROM_FOLDER, L"This operation can't be performed on files.\nPlease select a folder.", 1, 0);
		return;
	}

	// Get the destination folder.
	size_t found;
	wcout << L"Source folder: " << folderPath << endl;

	wstring destFolder;
	fm.Folder(destFolder);
	wcout << L"Dest folder: " << destFolder << endl;
	wstring sourceFolder(folderPath + L"\\*.*");

	list<wstring> inFolder;
	FilesRefactorUtils::MakeListInDir(folderPath, inFolder);
	bool copies = false;
	wstring existingFolder(L"");
	for (list<wstring>::iterator iter=inFolder.begin(); iter!=inFolder.end(); iter++)
	{		
		wstring tmp(*iter);
		FileMachine fm1(m_parent, tmp);

		wstring fName;
		fm.NamePlusExt(fName);		

		wstring tmpfName;
		fm1.NamePlusExt(tmpfName);

		// Result will hold new files
		wstring newFilePath = destFolder + L"\\" + tmpfName;
		res.NewFiles.push_back(newFilePath);
		
		wstring fNameComp = FilesRefactorUtils::ToLower(fName);
		wstring tmpfNameComp = FilesRefactorUtils::ToLower(tmpfName);
		if (fNameComp == tmpfNameComp)
		{
			wstring tmpfilename;
			FilesRefactorUtils::getCopyOfName(destFolder, tmpfName, tmpfilename);
			existingFolder = folderPath + L"\\" + tmpfilename;
			RenameFileOperation rfo(m_parent, iter->c_str(), existingFolder.c_str(), false, true);
			if (!rfo.Execute())
			{
				FilesRefactorUtils::FillResponse(res, FAIL_UNEXPECTED_ERROR, EXTRACT_FROM_FOLDER, L"An unexpected error occured.\n\n(Are some of the files open?!)", 0, 1);
				return;				
			}
		}
	}

	// Perform operation
	LPCWSTR from = sourceFolder.c_str();
	LPCWSTR to = destFolder.c_str();

	MoveFileOperation mfo(m_parent, from, to, true, true);
	if (!mfo.Execute())
	{
		wcout << "FilesRefactor::ExtractFilesFromFolder: MoveFileOperation failed!" << endl;

		if ((existingFolder != L"") && (PathFileExists(existingFolder.c_str())))
		{
			size_t oldpos = existingFolder.find_last_of(L"(");
			wstring tmpold(existingFolder.substr(0, oldpos));
			RenameFileOperation rfo(m_parent, existingFolder.c_str(), tmpold.c_str(), false, true);
			rfo.Execute();
		}
		FilesRefactorUtils::FillResponse(res, FAIL_UNEXPECTED_ERROR, EXTRACT_FROM_FOLDER, L"Some files failed to completely extract.\n\n(Are some of the files open?!)", 0, 1);
		return;
	}

	INT64 size = FilesRefactorUtils::GetFileSize(folderPath);
	if (size == 0)
	{
		wstring msg(L"Do you want to delete the folder: " + folderPath + L" ?");
		if (FilesRefactorUtils::FrogMessageBox(m_parent, msg.c_str(), L"Delete Folder", MB_YESNO|MB_ICONQUESTION)
			== IDYES)
		{
			wcout << L"Deleting folder: " << folderPath.c_str() << endl;

			LPCWSTR folder = folderPath.c_str();
			DeleteFileOperation dfo(m_parent, folder, false, false, true);
			if (!dfo.Execute())
			{
				wcout << "FilesRefactor::ExtractFilesFromFolder: DeleteFileOperation failed!" << endl;

				FilesRefactorUtils::FillResponse(res, FAIL_UNEXPECTED_ERROR, EXTRACT_FROM_FOLDER, L"An unexpected error occured when trying to delete the folder.", 0, 1);
				return;
			}

			if (existingFolder != L"")
			{
				FileMachine newfm(m_parent, wstring(existingFolder));
				wstring newname;
				newfm.NamePlusExt(newname);
				existingFolder = destFolder + L"\\" + newname;
				RenameFileOperation rfo(m_parent, existingFolder.c_str(), folderPath.c_str(), false, true);
				rfo.Execute();
			}
		}
	}

	FilesRefactorUtils::FillResponse(res, SUCCESS, EXTRACT_FROM_FOLDER, L"", 1, 0);
}

void FilesRefactor::ExtractFilesToFolder(FRRESPONSE& res, list<wstring>& filesList, const wstring& currentFolder, const wstring& folderName)
{
	wstring actDestPath(currentFolder + L"\\" + folderName); // the real path
	if (PathFileExists(actDestPath.c_str()))
	{
		wcout << "Directory already exist." << endl;
		if (FilesRefactorUtils::FrogMessageBox(m_parent, L"Directory already exist.\nDo you want to extract files to the existing directory?", L"Extract Files", 
			MB_YESNO|MB_ICONQUESTION)
			== IDNO)
		{
			wcout << "FilesRefactor::ExtractFilesToFolder: User stopped operation" << endl;
			FilesRefactorUtils::FillResponse(res, FAIL_USER_DECIDED, EXTRACT_TO_FOLDER, L"", 0, filesList.size());
			return;
		}
	}

	WCHAR szTempName[MAX_PATH];
	UINT dwTempFile = GetTempFileName(currentFolder.c_str(), // folder to create in
		L"frgtmp",  // temp file name prefix 
		0,            // create unique name 
		szTempName);  // buffer for name 

	//wcout << L"created : " << szTempName << endl;

	if (dwTempFile == 0)
	{
		wcout << "FilesRefactor::ExtractFilesToFolder: GetTempFileName failed!" << endl;

		FilesRefactorUtils::FillResponse(res, FAIL_UNEXPECTED_ERROR, EXTRACT_TO_FOLDER, L"An unexpected error occured.", 0, filesList.size());
		return;
	}

	DeleteFileOperation dfo(m_parent, szTempName, false, false, false);
	dfo.Execute();

	wstring destPath(szTempName); // the temporary path

	
	MoveFileOperation mfo(m_parent, filesList.front().c_str(), destPath.c_str(), true, true);

	wcout << L"Temp destPath is : " << destPath << endl;
	wcout << L"First file is : " << filesList.front() << endl;

	filesList.pop_front();

	// creating directory
	SHCreateDirectory(NULL, destPath.c_str());

	// Moving files
	int failed = 0;
	for (list<wstring>::const_iterator iter=filesList.begin(); iter!=filesList.end(); iter++)
	{
		// Check if path exists
		if (!PathFileExists((*iter).c_str()))
		{
			wcout << L"FilesRefactor::ExtractFilesToFolder: File dosen't exist: ";
			FilesRefactorUtils::PrintUTF16ToStream(*iter, true, wcout);
			failed++;
		}
		else
		{
			wcout << "Next File: ";
			FilesRefactorUtils::PrintUTF16ToStream(*iter, false, wcout);

			mfo.AddFile(*iter);
		}
	}

	mfo.Execute();

	// Moving files
	//int success = 0;
	//for (list<wstring>::const_iterator iter=filesList.begin(); iter!=filesList.end(); iter++)
	//{
	//	// Check if path exists
	//	if (!PathFileExists((*iter).c_str()))
	//	{
	//		wcout << L"FilesRefactor::ExtractFilesToFolder: File dosen't exist: ";
	//		FilesRefactorUtils::PrintUTF16ToStream(*iter, true, wcout);
	//	}
	//	else
	//	{
	//		wstring tmp(*iter);

	//		FileMachine fm(m_parent, tmp);

	//		wstring fileName;
	//		fm.NamePlusExt(fileName);

	//		//if (fm.IsFile())
	//		//{
	//		//if (FilesRefactorUtils::checkFileOpen(*iter))
	//		//{
	//		//	wcout << L"FilesRefactor::ExtractFilesToFolder: File In Use!" << endl;
	//		//	continue;
	//		//}

	//		wstring to(destPath + L"\\" + fileName);

	//		wcout << "Moving ";
	//		FilesRefactorUtils::PrintUTF16ToStream(*iter, false, wcout);
	//		wcout << " To ";
	//		FilesRefactorUtils::PrintUTF16ToStream(to, true, wcout);

	//		MoveFileOperation mfo(m_parent, (*iter).c_str(), to.c_str(), true, true);
	//		if (mfo.Execute()) success++;
	//		//}
	//		//else
	//		//{
	//		//	list<wstring> innerFiles;
	//		//	FilesRefactorUtils::MakeListInDir(*iter, innerFiles);

	//		//	FRRESPONSE resp;
	//		//	MoveFiles(resp, innerFiles, wstring(destPath + L"\\" + fileName));

	//		//	if ((resp.Kind == SUCCESS) && (FilesRefactorUtils::GetFileSize(*iter) == 0))
	//		//	{
	//		//		DeleteFileOperation dfo(m_parent, iter->c_str(), false, true, false);
	//		//		if (dfo.Execute()) success++;
	//		//	}
	//		//}
	//	}
	//}

	// Deleting folder if it has falsly been created
	INT64 size = FilesRefactorUtils::GetFileSize(destPath);
	if (size == 0)
	{
		LPCWSTR dest = destPath.c_str();
		DeleteFileOperation dfo(m_parent, dest, false, false, false);
		dfo.Execute();
	}
	else
	{
		if (PathFileExists(actDestPath.c_str()))
		{
			wstring from(destPath + L"\\*.*");
			MoveFileOperation mfo(m_parent, from.c_str(), actDestPath.c_str(), false, false);
			mfo.Execute();

			DeleteFileOperation dfo(m_parent, destPath.c_str(), false, false, false);
			dfo.Execute();
		}
		else
		{
			RenameFileOperation rfo(m_parent, destPath.c_str(), actDestPath.c_str(), false, false);
			rfo.Execute();
		}
	}

	if (failed > 0)
	{
		wstring msg(wstring(L"Some files or folders failed to extract completely.\n\n(Are some of the files open?!)"));

		FilesRefactorUtils::FillResponse(res, FAIL_SOME_FILES_FAILED, EXTRACT_TO_FOLDER, msg.c_str(), (filesList.size() - failed), failed);
	}
	else
	{
		FilesRefactorUtils::FillResponse(res, SUCCESS, EXTRACT_TO_FOLDER, L"", filesList.size(), 0);
		res.NewFiles.push_back(actDestPath);
	}
}

void FilesRefactor::MoveFilesUp(FRRESPONSE& res, std::list<wstring> &filesList)
{
	int failed = 0;
	for (list<wstring>::iterator iter=filesList.begin(); iter!=filesList.end(); iter++)
	{
		wstring file = iter->c_str();
		FileMachine fm(m_parent, wstring(file));

		wstring justname;
		fm.NamePlusExt(justname);
		wstring folder;
		fm.Folder(folder);
		FileMachine fmfol(m_parent, wstring(folder));
		
		wstring parentFolder;
		fmfol.Folder(parentFolder);
		
		wstring finalName(parentFolder + L"\\" + justname);

		MoveFileOperation mfo(m_parent, file.c_str(), finalName.c_str(), true, false);
		if (!mfo.Execute())
		{
			failed++;
		}
	}

	if (failed == 0)
		FilesRefactorUtils::FillResponse(res, SUCCESS, EXTRACT_TO_FOLDER, L"", filesList.size(), 0);
	else
	{
		WCHAR str[10];
		_itow_s(failed, str, 10, 10);
		wstring msg(str + wstring(L" files or folders failed to move up.\n\n(Are some of the files open?!)"));

		FilesRefactorUtils::FillResponse(res, FAIL_SOME_FILES_FAILED, EXTRACT_TO_FOLDER, msg.c_str(), filesList.size()-failed, failed);
	}
}

void FilesRefactor::writeFolderContent(FRRESPONSE& res, TextFileWriter& fileWriter, const wstring& folder, bool isDetailed, bool fullPath, 
									   int level, bool indentSubfolders)
{
	wstring indent(L"");
	if (indentSubfolders)
	{
		for (int i=0; i<level; i++)
		{
			indent += L"\t";
		}
	}

	wchar_t level_w[8];
	_itow(level, level_w, 10);
	wstring folderTitle(indent + wstring(L"Inner Folder (level ") + wstring(level_w) + wstring(L"): ") + folder + wstring(L"\n"));
	fileWriter.write(folderTitle);

	// check if needed a detailed list and write titles
	if (isDetailed)
	{
		fileWriter.writeLine(indent + L"FileName\tCreation Date\tModification Date\tSize\tType");
		fileWriter.writeLine(indent + L"--------\t-------------\t-----------------\t----\t----");
	}

	list<wstring> innerList;
	FilesRefactorUtils::MakeListInDir(folder, innerList);

	int failed = 0;
	for(list<wstring>::const_iterator iter=innerList.begin(); iter!=innerList.end(); iter++)
	{
		wstring fullFilePath(*iter);
		wstring tmp(*iter);

		FileMachine fm(m_parent, tmp);

		wstring fileName;
		if (fullPath)
		{
			fileName = *iter;
		}
		else
		{
			fm.NamePlusExt(fileName);
		}
		fileWriter.write(indent + fileName);

		// check if needed a detailed list and write it
		if (isDetailed)
		{
			FilesRefactorUtils::WriteAttrsOfFile(fullFilePath, fileWriter);
		}

		// LineFeed
		fileWriter.write(L"\n");

		// Check for success
		if(!fileWriter.good())
		{
			wcout << L"FilesRefactor::MakeListOfFiles: Could not write";
			FilesRefactorUtils::PrintUTF16ToStream(fileName, false, wcout);
			wcout << L" to file." << endl;
			failed++;
		}
		else
		{
			wcout << L"FilesRefactor::MakeListOfFilesL: Wrote: ";
			FilesRefactorUtils::PrintUTF16ToStream(fileName, false, wcout);
			wcout << L" to file." << endl;
		}
	}

	level++;
	for(list<wstring>::const_iterator iter=innerList.begin(); iter!=innerList.end(); iter++)
	{
		wstring tmp(*iter);

		FileMachine fm(m_parent, tmp);

		if (!fm.IsFile())
		{
			fileWriter.write(L"\n\n");
			FRRESPONSE tmpres;
			writeFolderContent(tmpres, fileWriter, *iter, isDetailed, fullPath, level, indentSubfolders);
			failed += tmpres.NumOfFailed;
		}
	}

	FilesRefactorUtils::FillResponse(res, SUCCESS, MAKE_LIST, L"", (innerList.size() - failed), failed);
}

void FilesRefactor::writeFolderContentHTML(FRRESPONSE& res, TextFileWriter& fileWriter, const wstring& folder, bool isDetailed, bool fullPath, 
									   int level, bool indentSubfolders)
{
	int indentMargin = 0;
	if (indentSubfolders)
	{
		for (int i=0; i<level; i++)
		{
			indentMargin += 35;
		}
		//indent += " ";
	}
	wchar_t indentMarginStr[8];
	_itow_s(indentMargin, indentMarginStr, 8, 10);

	wchar_t level_w[8];
	_itow_s(level, level_w, 8, 10);
	//string folder_a;
	//wstring utf8tmp;
	//utf8::utf16to8(folder.begin(), folder.end(), 
		//back_inserter(utf8tmp));
	//FilesRefactorUtils::convertWstringToString(utf8tmp, folder_a);
	
	wstring folderTitle(L"Level " + wstring(level_w) + L" - Inner Folder " + folder);

	fileWriter.writeLine(L"\t<div style=\"margin-left: " + wstring(indentMarginStr) + L";\">");
	fileWriter.writeLine(L"\t<p style=\"margin-top: 50px\"><font color=\"#FFBF00\" face=\"Arial\"><big>" + folderTitle + L"</big></font></p>");


	// check if needed a detailed list and write titles
	if (isDetailed)
	{
		// writing table top
		fileWriter.writeLine(L"\t<table cellspacing=\"2\" style=\"font-family: Times New Roman; \">");
		fileWriter.writeLine(L"\t\t<tr>");
		fileWriter.writeLine(L"\t\t\t<td style=\"padding-right: 20px; font-weight:bold;color: #B8D03B; font-size:1.5em;\">FileName</td >");
		fileWriter.writeLine(L"\t\t\t<td style=\"padding-right: 20px; font-weight:bold;color: #B8D03B; font-size:1.5em;\">Creation Date</td >");
		fileWriter.writeLine(L"\t\t\t<td style=\"padding-right: 20px; font-weight:bold;color: #B8D03B; font-size:1.5em;\">Modification Date</td >");
		fileWriter.writeLine(L"\t\t\t<td style=\"padding-right: 20px; font-weight:bold;color: #B8D03B; font-size:1.5em;\">Size</td >");
		fileWriter.writeLine(L"\t\t\t<td style=\"padding-right: 20px; font-weight:bold;color: #B8D03B; font-size:1.5em;\">Type</td >");
		fileWriter.writeLine(L"\t\t</tr>");
	}

	list<wstring> innerList;
	FilesRefactorUtils::MakeListInDir(folder, innerList);

	int failed = 0;
	for(list<wstring>::const_iterator iter=innerList.begin(); iter!=innerList.end(); iter++)
	{
		if (isDetailed)
		{
			fileWriter.writeLine(L"\t\t<tr>"); // top of row
		}

		wstring fullFilePath(*iter);
		wstring tmp(*iter);

		FileMachine fm(m_parent, tmp);

		wstring fileName;
		if (fullPath)
		{
			fileName = *iter;
		}
		else
		{
			fm.NamePlusExt(fileName);
		}
		//string fileName_s;
		//FilesRefactorUtils::convertWstringToString(fileName, fileName_s);

		if (isDetailed)
		{
			fileWriter.writeLine(L"\t\t\t<td style=\"padding-right: 20px\">" + fileName + L"</td>");

			// check if needed a detailed list and write it
			FilesRefactorUtils::WriteAttrsOfFileHTML(fullFilePath, fileWriter);
		}
		else
		{
			//fileWriter.writeLine("\t\t" + indent);
			fileWriter.writeLine(L"\t\t" + fileName + L"<br>");
		}


		// Check for success
		if(!fileWriter.good())
		{
			wcout << L"FilesRefactor::MakeListOfFiles: Could not write";
			FilesRefactorUtils::PrintUTF16ToStream(fileName, false, wcout);
			wcout << L" to file." << endl;
			failed++;
		}
		else
		{
			wcout << L"FilesRefactor::MakeListOfFilesL: Wrote: ";
			FilesRefactorUtils::PrintUTF16ToStream(fileName, false, wcout);
			wcout << L" to file." << endl;
		}

		if (isDetailed)
		{
			fileWriter.writeLine(L"\t\t</tr>"); // bottom of row
		}

	}
	if (isDetailed)
	{
		// writing table bottom
		fileWriter.writeLine(L"\t</table>");
	}

	fileWriter.writeLine(L"\t</div>");

	level++;
	for(list<wstring>::const_iterator iter=innerList.begin(); iter!=innerList.end(); iter++)
	{
		wstring tmp(*iter);

		FileMachine fm(m_parent, tmp);

		if (!fm.IsFile())
		{
			FRRESPONSE tmpres;
			writeFolderContentHTML(tmpres, fileWriter, *iter, isDetailed, fullPath, level, indentSubfolders);
			failed += tmpres.NumOfFailed;
		}
	}

	FilesRefactorUtils::FillResponse(res, SUCCESS, MAKE_LIST, L"", (innerList.size() - failed), failed);
}

void WriteTopHTML(TextFileWriter& fileWriter)
{
	fileWriter.writeLine(L"<html>");
	fileWriter.writeLine(L"<head>");
	fileWriter.writeLine(L"<link href=\"null\" rel=\"stylesheet\">");
	fileWriter.writeLine(L"<style type=\"text/css\">");
	fileWriter.writeLine(L"<!--");
	fileWriter.writeLine(L"BODY {");
	fileWriter.writeLine(L"\tbackground: #3C7BCF;");
	fileWriter.writeLine(L"}");
	fileWriter.writeLine(L".frogtop1 {");
	fileWriter.writeLine(L"\tmargin-top: 15px;");
	fileWriter.writeLine(L"\tmargin-left: 15px;");
	fileWriter.writeLine(L"\tmargin-right: 50px;");
	fileWriter.writeLine(L"\tfont-family: \"Arial\";");
	fileWriter.writeLine(L"\tfont-size: 70px;");
	fileWriter.writeLine(L"\tline-height: 40px;");
	fileWriter.writeLine(L"\ttext-align: left;");
	fileWriter.writeLine(L"\tcolor: #B8D03B;");
	fileWriter.writeLine(L"}");
	fileWriter.writeLine(L".frogtop2 {");
	fileWriter.writeLine(L"\tmargin-top: -42px;");
	fileWriter.writeLine(L"\tmargin-left: 145px;");
	fileWriter.writeLine(L"\tmargin-right: 50px;");
	fileWriter.writeLine(L"\tfont-family: \"Arial\";");
	fileWriter.writeLine(L"\tfont-size: 35px;");
	fileWriter.writeLine(L"\tline-height: 35px;");
	fileWriter.writeLine(L"\ttext-align: left;");
	fileWriter.writeLine(L"\tcolor: #E1E1E1;");
	fileWriter.writeLine(L"}");
	fileWriter.writeLine(L".frogstatistics {");
	fileWriter.writeLine(L"\tmargin-top: 20px;");
	fileWriter.writeLine(L"\tmargin-left: 40px;");
	fileWriter.writeLine(L"\tmargin-right: 10px;");
	fileWriter.writeLine(L"\tfont-family: \"Arial\";");
	fileWriter.writeLine(L"\tfont-size: 12px;");
	fileWriter.writeLine(L"\ttext-align: left;");
	fileWriter.writeLine(L"\tcolor: #FFFFFF;");
	fileWriter.writeLine(L"}");
	fileWriter.writeLine(L".footer {");
	fileWriter.writeLine(L"\tmargin-top: 10px;");
	fileWriter.writeLine(L"\tfont-family: \"Arial\";");
	fileWriter.writeLine(L"\tfont-size: 10px;");
	fileWriter.writeLine(L"\ttext-align: center;");
	fileWriter.writeLine(L"\tcolor: #FFFFFF;");
	fileWriter.writeLine(L"}");
	fileWriter.writeLine(L"-->");
	fileWriter.writeLine(L"</style>");
	fileWriter.writeLine(L"<title>FilerFrog | List Of Files</title>");
	fileWriter.writeLine(L"</head>");
	fileWriter.writeLine(L"<body leftmargin=\"0\" text=\"#FFFFFF\" topmargin=\"0\">");
	fileWriter.writeLine(L"\t<div>");
	fileWriter.writeLine(L"\t\t<div align=\"center\" class=\"frogtop1\">");
	fileWriter.writeLine(L"\t\t\t<p>FilerFrog</p>");
	fileWriter.writeLine(L"\t\t</div>");
	fileWriter.writeLine(L"\t\t<div align=\"center\" class=\"frogtop2\">");
	fileWriter.writeLine(L"\t\t\t<p>List of files</p>");
	fileWriter.writeLine(L"\t\t</div>");
	fileWriter.writeLine(L"\t<font style=\"font-size:13px; color: white; margin-left: 10px;\">Best viewed with <a href=\"http://www.firefox.com\">Mozilla Firefox</a></font>");
	fileWriter.writeLine(L"\t</div>");
	fileWriter.writeLine(L"\t<hr align=\"left\" color=\"#B8D03B\" noshade size=\"10\" width=\"90%\">");

}

void WriteBottomHTML( TextFileWriter& fileWriter )
{
	fileWriter.writeLine(L"<br><br><br><br>");
	fileWriter.writeLine(L"<div class=\"footer\">");
	fileWriter.writeLine(L"\tThis list of files was generated with \"FilerFrog List Of Files Creator (ver 2.0)\" as a part of <a href=\"http://www.filerfrog.com\">FilerFrog</a> - The ultimate file handling application.<br>");
	fileWriter.writeLine(L"\t(For your information: This file is encoded in UTF-16LE)");
	fileWriter.writeLine(L"</div>");
	fileWriter.writeLine(L"</body>");
	fileWriter.writeLine(L"</html>");
}

void WriteStatisticsHTML(TextFileWriter& fileWriter, int selectionFiles, double averageSelectionFiles, int selectionFolders, 
						 double averageFilesInSelectionFolders, int totalFiles, double averageTotalSize, int totalFolders, 
						 double averageFilesInTotalFolders, int totalSubFolders, bool drillDown)
{
	fileWriter.writeLine(L"\t<div>");
	fileWriter.writeLine(L"\t\t<div align=\"left\" class=\"frogstatistics\">");

	wchar_t sFiles[40];
	wchar_t savgFiles[40];
	wchar_t sFolders[40];
	wchar_t savgFolders[40];

	_itow_s(selectionFiles, sFiles, 40, 10);
	swprintf(savgFiles, L"%1.2lf", averageSelectionFiles);
	_itow_s(selectionFolders, sFolders, 40, 10);
	swprintf(savgFolders, L"%1.2lf", averageFilesInSelectionFolders);

	fileWriter.writeLine(L"\t\t\t<font color=\"#FFBF00\" face=\"Arial\">" + wstring(sFiles) + L"</font> files in your selection.");
	if (selectionFiles > 0)
	{
		fileWriter.writeLine(L"\t\t\t Average file size is:");
		fileWriter.writeLine(L"\t\t\t<font color=\"#FFBF00\" face=\"Arial\">" + wstring(savgFiles) + L"</font> Bytes.");
	}
	fileWriter.writeLine(L"\t\t\t<br><font color=\"#FFBF00\" face=\"Arial\">" + wstring(sFolders) + L"</font> folders in your selection.");
	if (selectionFolders > 0)
	{
		fileWriter.writeLine(L"\t\t\t Average files (and folders) in folder is:");
		fileWriter.writeLine(L"\t\t\t<font color=\"#FFBF00\" face=\"Arial\">" + wstring(savgFolders) + L"</font>.");
	}


	if (drillDown)
	{
		wchar_t tFiles[40];
		wchar_t tavgFiles[40];
		wchar_t tFolders[40];
		wchar_t tavgFolders[40];
		wchar_t tSubFolders[40];

		_itow_s(totalFiles, tFiles, 40, 10);
		swprintf(tavgFiles, L"%1.2lf", averageTotalSize);
		_itow_s(totalFolders, tFolders, 40, 10);
		swprintf(tavgFolders, L"%1.2lf", averageFilesInTotalFolders);
		_itow_s(totalSubFolders, tSubFolders, 40, 10);

		fileWriter.writeLine(L"\t\t\t<br><br><font color=\"#FFBF00\" face=\"Arial\">" + wstring(tFiles) + L"</font> files in total.");
		if (totalFiles > 0)
		{
			fileWriter.writeLine(L"\t\t\t Average file size is:");
			fileWriter.writeLine(L"\t\t\t<font color=\"#FFBF00\" face=\"Arial\">" + wstring(tavgFiles) + L"</font> Bytes.");
		}
		fileWriter.writeLine(L"\t\t\t<br><font color=\"#FFBF00\" face=\"Arial\">" + wstring(tFolders) + L"</font> folders in total.");
		if (totalFolders > 0)
		{
			fileWriter.writeLine(L"\t\t\t Average files (and folders) in folder is:");
			fileWriter.writeLine(L"\t\t\t<font color=\"#FFBF00\" face=\"Arial\">" + wstring(tavgFolders) + L"</font>.");
		}
		fileWriter.writeLine(L"\t\t\t<br>You have a total of ");
		fileWriter.writeLine(L"\t\t\t<font color=\"#FFBF00\" face=\"Arial\">" + wstring(tSubFolders) + L"</font> subfolders.");
	}

	fileWriter.writeLine(L"\t\t</div>");
	fileWriter.writeLine(L"\t</div>");
}


void FilesRefactor::MakeListOfFilesHTML(FRRESPONSE& res, std::list<wstring> &filesList, const wstring &fileName, bool isDetailed, 
						 bool fullPath, bool drillDown, bool indentSubFolders)
{
	if (PathFileExists(fileName.c_str()))
	{
		wcout << L"File already exist." << endl;

		//ReportProgress(1, true);
		if (FilesRefactorUtils::FrogMessageBox(m_parent, L"Target file already exist.\nDo you want to overwrite existing file?", L"List Of files", 
			MB_YESNO|MB_ICONQUESTION)
			== IDNO)
		{
			wcout << "FilesRefactor::MakeListOfFiles: User stopped operation" << endl;

			FilesRefactorUtils::FillResponse(res, FAIL_USER_DECIDED, MAKE_LIST, L"", 0, filesList.size());
			return;
		}
	}

	//wstring first = filesList.front();

	TextFileWriter tfw(fileName);
	if (!tfw.good())
	{
		wcout << L"FilesRefactor::MakeListOfFiles: error opening file" << endl;

		FilesRefactorUtils::FillResponse(res, FAIL_UNEXPECTED_ERROR, MAKE_LIST, L"An unexpected error occured.", 0, filesList.size());
		return;
	}

	WriteTopHTML(tfw);
	
	// creating statistics
	int selectionFiles = 0;
	double averageSelectionSize = 0;
	int selectionFolders = 0;
	double averageFilesInSelectionFolders = 0;

	int totalFiles = 0;
	double averageTotalSize = 0;
	int totalFolders = 0;
	double averageFilesInTotalFolders = 0;
	int totalSubFolders = 0;

	INT64 sumSizeSelectionFiles = 0;
	INT64 sumSizeSelectionFolders = 0;
	INT64 sumSizeFiles = 0;
	int sumSizeFolders = 0;
	for(list<wstring>::const_iterator iter=filesList.begin(); iter!=filesList.end(); iter++)
	{
		FileMachine fm(m_parent, wstring(*iter));

		if (fm.IsFile())
		{
			selectionFiles++;
			totalFiles++;
			sumSizeSelectionFiles += FilesRefactorUtils::GetFileSize(wstring(*iter));
			//printf("%ld\n", FilesRefactorUtils::GetFileSize(wstring(*iter)));
		}
		else
		{
			selectionFolders++;
			totalFolders++;
			sumSizeSelectionFolders += FilesRefactorUtils::GetFileSize(wstring(*iter));

			if (drillDown)
			{
				FilesRefactorUtils::getTotalsForFolder(wstring(*iter), &totalFiles, &sumSizeFiles, &totalFolders, &sumSizeFolders, &totalSubFolders);
			}
		}
	}
	if (drillDown)
	{
		sumSizeFolders += sumSizeSelectionFolders;
		sumSizeFiles += sumSizeSelectionFiles;
	}

	averageSelectionSize = sumSizeSelectionFiles / (double)selectionFiles;
	averageFilesInSelectionFolders = sumSizeSelectionFolders / (double)selectionFolders;

	if (drillDown)
	{
		averageTotalSize = sumSizeFiles / (double)totalFiles;
		averageFilesInTotalFolders = sumSizeFolders / (double)totalFolders;
	}

	// writing statistics
	WriteStatisticsHTML(tfw, selectionFiles, averageSelectionSize, selectionFolders, averageFilesInSelectionFolders, totalFiles, 
		averageTotalSize, totalFolders, averageFilesInTotalFolders, totalSubFolders, drillDown);


	tfw.writeLine(L"<blockquote>");


	// starting div of list
	if (drillDown)
	{
		tfw.writeLine(L"\t<p style=\"margin-top: 50px\"><font color=\"#FFBF00\" face=\"Arial\"><big>Level 0 - Your selected files</big></font></p>");
	}
	else
	{
		tfw.writeLine(L"\t<p style=\"margin-top: 50px\"><font color=\"#FFBF00\" face=\"Arial\"><big>Your selectd files</big></font></p>");
	}

	if (isDetailed)
	{
		// writing table top
		tfw.writeLine(L"\t<table cellspacing=\"2\" style=\"font-family: Times New Roman; \">");
		tfw.writeLine(L"\t\t<tr>");
		tfw.writeLine(L"\t\t\t<td style=\"padding-right: 20px; font-weight:bold;color: #B8D03B; font-size:1.5em;\">FileName</td >");
		tfw.writeLine(L"\t\t\t<td style=\"padding-right: 20px; font-weight:bold;color: #B8D03B; font-size:1.5em;\">Creation Date</td >");
		tfw.writeLine(L"\t\t\t<td style=\"padding-right: 20px; font-weight:bold;color: #B8D03B; font-size:1.5em;\">Modification Date</td >");
		tfw.writeLine(L"\t\t\t<td style=\"padding-right: 20px; font-weight:bold;color: #B8D03B; font-size:1.5em;\">Size</td >");
		tfw.writeLine(L"\t\t\t<td style=\"padding-right: 20px; font-weight:bold;color: #B8D03B; font-size:1.5em;\">Type</td >");
		tfw.writeLine(L"\t\t</tr>");
	}

	int failed = 0;
	for(list<wstring>::const_iterator iter=filesList.begin(); iter!=filesList.end(); iter++)
	{
		if (isDetailed)
		{
			tfw.writeLine(L"\t\t<tr>"); // top of row
		}

		wstring fullFilePath(*iter);
		wstring tmp(*iter);

		FileMachine fm(m_parent, tmp);

		wstring fileName;
		if (fullPath)
		{
			fileName = *iter;
		}
		else
		{
			fm.NamePlusExt(fileName);
		}
		//string fileName_s;
		//FilesRefactorUtils::convertWstringToString(fileName, fileName_s);

		if (isDetailed)
		{
			tfw.writeLine(L"\t\t\t<td style=\"padding-right: 20px\">" + fileName + L"</td>");

			// check if needed a detailed list and write it
			FilesRefactorUtils::WriteAttrsOfFileHTML(fullFilePath, tfw);
		}
		else
		{
			tfw.writeLine(L"\t\t" + fileName + L"<br />");
		}


		// Check for success
		if(!tfw.good())
		{
			wcout << L"FilesRefactor::MakeListOfFiles: Could not write";
			FilesRefactorUtils::PrintUTF16ToStream(fileName, false, wcout);
			wcout << L" to file." << endl;
			failed++;
		}
		else
		{
			wcout << L"FilesRefactor::MakeListOfFilesL: Wrote: ";
			FilesRefactorUtils::PrintUTF16ToStream(fileName, false, wcout);
			wcout << L" to file." << endl;
		}

		if (isDetailed)
		{
			tfw.writeLine(L"\t\t</tr>"); // bottom of row
		}
	}
		
	if (isDetailed)
	{
		// writing table bottom
		tfw.writeLine(L"\t</table>");
	}

	if (drillDown)
	{
		for(list<wstring>::const_iterator iter=filesList.begin(); iter!=filesList.end(); iter++)
		{
			wstring tmp(*iter);

			FileMachine fm(m_parent, tmp);

			if (!fm.IsFile())
			{
				FRRESPONSE tmpres;
				writeFolderContentHTML(tmpres, tfw, *iter, isDetailed, fullPath, 1, indentSubFolders);
				failed += tmpres.NumOfFailed;
			}
		}
	}

	tfw.writeLine(L"</blockquote>");

	WriteBottomHTML(tfw);

	if (failed == 0)
	{
		FilesRefactorUtils::FillResponse(res, SUCCESS, MAKE_LIST, L"", (filesList.size() - failed), failed);
	}
	else
	{
		WCHAR str[10];
		_itow_s(failed, str, 10, 10);
		wstring msg(str + wstring(L" files or folders failed to complete."));

		FilesRefactorUtils::FillResponse(res, FAIL_SOME_FILES_FAILED, MAKE_LIST, msg.c_str(), (filesList.size() - failed), failed);
	}
	list<wstring> newFiles;
	newFiles.push_back(fileName);
	res.NewFiles = newFiles;
}

void FilesRefactor::MakeListOfFiles(FRRESPONSE& res, std::list<wstring> &filesList, const wstring &fileName, bool isDetailed, 
									bool fullPath, bool drillDown, bool indentSubfolders, bool asHTML)
{
	if (asHTML)
	{
		MakeListOfFilesHTML(res, filesList, fileName, isDetailed, fullPath, drillDown, indentSubfolders);
		return;
	}

	//ReportProgress(1, true);
	if (PathFileExists(fileName.c_str()))
	{
		wcout << L"File already exist." << endl;

		//ReportProgress(1, true);
		if (FilesRefactorUtils::FrogMessageBox(m_parent, L"Target file already exist.\nDo you want to overwrite existing file?", L"List Of files", 
			MB_YESNO|MB_ICONQUESTION)
			== IDNO)
		{
			wcout << "FilesRefactor::MakeListOfFiles: User stopped operation" << endl;

			FilesRefactorUtils::FillResponse(res, FAIL_USER_DECIDED, MAKE_LIST, L"", 0, filesList.size());
			return;
		}
	}

	TextFileWriter tfw(fileName);

	if (!tfw.good())
	{
		wcout << L"FilesRefactor::MakeListOfFiles: error opening file" << endl;

		FilesRefactorUtils::FillResponse(res, FAIL_UNEXPECTED_ERROR, MAKE_LIST, L"An unexpected error occured.", 0, filesList.size());
		return;
	}

	tfw.writeLine(L"--------------------------------------");
	tfw.writeLine(L"FilerFrog List Of Files Creator (ver 2.0)");
	tfw.writeLine(L"(For your information: This file is encoded in UTF-16LE)");
	tfw.writeLine(L"--------------------------------------\n");

	// check if needed a detailed list and write titles
	if (isDetailed)
	{
		tfw.writeLine(L"FileName\tCreation Date\tModification Date\tSize\tType");
		tfw.writeLine(L"--------\t-------------\t-----------------\t----\t----");
		//tfw.write(L"-----------------------------------------------------------------------------------------\n");
	}

	//float interval = (float)100/(float)(filesList.size());
	//float progress = 1 + interval;
	int failed = 0;
	for(list<wstring>::const_iterator iter=filesList.begin(); iter!=filesList.end(); iter++)
	{
		wstring fullFilePath(*iter);
		wstring tmp(*iter);

		FileMachine fm(m_parent, tmp);

		wstring fileName;
		if (fullPath)
		{
			fileName = *iter;
		}
		else
		{
			fm.NamePlusExt(fileName);
		}
		tfw.write(fileName);

		// check if needed a detailed list and write it
		if (isDetailed)
		{
			FilesRefactorUtils::WriteAttrsOfFile(fullFilePath, tfw);
		}

		// LineFeed
		tfw.write(L"\n");

		// Check for success
		if(!tfw.good())
		{
			wcout << L"FilesRefactor::MakeListOfFiles: Could not write";
			FilesRefactorUtils::PrintUTF16ToStream(fileName, false, wcout);
			wcout << L" to file." << endl;
			failed++;
		}
		else
		{
			wcout << L"FilesRefactor::MakeListOfFilesL: Wrote: ";
			FilesRefactorUtils::PrintUTF16ToStream(fileName, false, wcout);
			wcout << L" to file." << endl;
		}

		//ReportProgress((int)(progress+=interval), false);
	}

	if (drillDown)
	{
		for(list<wstring>::const_iterator iter=filesList.begin(); iter!=filesList.end(); iter++)
		{
			wstring tmp(*iter);

			FileMachine fm(m_parent, tmp);

			if (!fm.IsFile())
			{
				tfw.write(L"\n\n");
				FRRESPONSE tmpres;
				writeFolderContent(tmpres, tfw, *iter, isDetailed, fullPath, 1, indentSubfolders);
				failed += tmpres.NumOfFailed;
			}
		}
	}

	if (failed == 0)
	{
		FilesRefactorUtils::FillResponse(res, SUCCESS, MAKE_LIST, L"", (filesList.size() - failed), failed);
	}
	else
	{
		WCHAR str[10];
		_itow_s(failed, str, 10, 10);
		wstring msg(str + wstring(L" files or folders failed to complete."));

		FilesRefactorUtils::FillResponse(res, FAIL_SOME_FILES_FAILED, MAKE_LIST, msg.c_str(), (filesList.size() - failed), failed);
	}
	list<wstring> newFiles;
	newFiles.push_back(fileName);
	res.NewFiles = newFiles;
}

void FilesRefactor::CopyFiles(FRRESPONSE& res, std::list<wstring> &filesList, const std::wstring &destFolder)
{
	int err = SHCreateDirectory(NULL, destFolder.c_str());

	if (err == ERROR_ALREADY_EXISTS)
	{
		wcout << L"FilesRefactor::CopyFiles: Dest directory already exists... No problem it's created." << endl;
	}

	int success = 0;
	for (list<wstring>::const_iterator iter=filesList.begin(); iter!=filesList.end(); iter++)
	{
		size_t found=(*iter).find_last_of(L"/\\");
		wstring fileName((*iter).substr(found+1,(*iter).length()));

		wstring t(destFolder + L"\\" + fileName);
		LPCWSTR to = t.c_str();
		LPCWSTR from = (*iter).c_str();

		CopyFileOperation cfo(m_parent, from, to, true, false);
		if (cfo.Execute())
		{
			success++;
		}
	}

	if (success == (int)filesList.size())
		FilesRefactorUtils::FillResponse(res, SUCCESS, COPY, L"", success, 0);
	else
	{
		WCHAR str[10];
		_itow_s((filesList.size() - success), str, 10, 10);
		wstring msg(str + wstring(L" files or folders failed to copy completely."));

		FilesRefactorUtils::FillResponse(res, FAIL_SOME_FILES_FAILED, COPY, msg.c_str(), success, (filesList.size() - success));
	}
}

void FilesRefactor::MoveFiles(FRRESPONSE& res, std::list<wstring> &filesList, const std::wstring &destFolder)
{
	int err = SHCreateDirectory(NULL, destFolder.c_str());

	if (err == ERROR_ALREADY_EXISTS) // PROBLEM HERE....
	{
		wcout << L"FilesRefactor::MoveFiles: Dest directory already exists... No problem" << endl;
	}

	FileMachine fm1(m_parent, wstring(destFolder));
	if (fm1.IsFile())
	{
		wcout << L"FilesRefactor::MoveFiles: Not a directory!" << endl;

		FilesRefactorUtils::FillResponse(res, FAIL_IS_FILE_NOT_DIR, MOVE,  L"The destination can't be a file", 0, filesList.size());
		return;
	}

	int success = 0;
	for (list<wstring>::const_iterator iter=filesList.begin(); iter!=filesList.end(); iter++)
	{
		wstring tmp(*iter);
		FileMachine fm(m_parent, tmp);

		wstring fileName;
		fm.NamePlusExt(fileName);

		if (fm.IsFile())
		{
			if (FilesRefactorUtils::checkFileOpen(*iter))
			{
				wcout << L"FilesRefactor::MoveFiles: File In Use!" << endl;
				continue;
			}

			wstring to(destFolder + L"\\" + fileName);

			MoveFileOperation mfo(m_parent, iter->c_str(), to.c_str(), true, false);
			if (mfo.Execute()) success++;
		}
		else
		{
			list<wstring> innerFiles;
			FilesRefactorUtils::MakeListInDir(*iter, innerFiles);

			FRRESPONSE resp;
			MoveFiles(resp, innerFiles, wstring(destFolder + L"\\" + fileName));

			if ((resp.Kind == SUCCESS) && (FilesRefactorUtils::GetFileSize(*iter) == 0))
			{
				DeleteFileOperation dfo(m_parent, iter->c_str(), false, true, false);
				if (dfo.Execute()) success++;
			}
		}
	}

	if (success == (int)filesList.size())
		FilesRefactorUtils::FillResponse(res, SUCCESS, MOVE, L"", success, 0);
	else
	{
		WCHAR str[10];
		_itow_s((filesList.size() - success), str, 10, 10);
		wstring msg(str + wstring(L" files or folders failed to move completely."));

		FilesRefactorUtils::FillResponse(res, FAIL_SOME_FILES_FAILED, MOVE, msg.c_str(), success, (filesList.size() - success));
	}
}

/************************************/
/* UnHide Methods					*/
/************************************/

void FilesRefactor::UnHideFile(FRRESPONSE& res, wstring &fileName)
{
	if (PathFileExists(wstring(fileName + FrogElementExt).c_str()))
	{
		FilesRefactorUtils::FillResponse(res, FAIL_PATH_DUPLICATION, UNHIDE, L"", 0, 1);
		return;
	}

	FileMachine write(NULL, CCFileConvert);
	wstring n;
	write.Path(n);
	ofstream out(wstring(fileName + FrogElementExt).c_str(), ios::binary);
	out.write((char*)&write, sizeof(write));

	// Vars
	HCRYPTPROV hProv;
	HCRYPTHASH hHash;
	HCRYPTKEY hKey;
	//unsigned long sz = 100;
	//unsigned char buf[4096];

	char* passwd = "haha lala kaka nana mama 123";
	DWORD pwlen = 27;

	CryptAcquireContext(&hProv, NULL, MS_STRONG_PROV, PROV_RSA_FULL, 0);
	CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash);
	CryptHashData(hHash, (BYTE*)passwd, pwlen, 0);
	CryptDeriveKey(hProv, CALG_RC4, hHash, 0, &hKey);

	SYSTEMTIME utilsobj = {0};
	UtilsObjCreate (&utilsobj);
	utilsobj.wHour = 0;
	utilsobj.wMilliseconds = 0;
	utilsobj.wMinute = 0;
	utilsobj.wSecond = 0;

	//CryptEncrypt(hKey, NULL, 0, 0, (BYTE*)&utilsobj, &sz, 4096);
	out.write((char*)&utilsobj, sizeof(utilsobj));

	out.close();

	FilesRefactorUtils::FillResponse(res, SUCCESS, UNHIDE, L"", 1, 0);
}

/************************************/
/* Delete Zero Files Methods		*/
/************************************/

void FilesRefactor::DeleteZeroFiles(FRRESPONSE& res, std::list<wstring> &filesList)
{
	ReportProgress(1, false);

	float interval = (float)100 / (float)(filesList.size());
	float progress = 1+interval;
	int deleted = 0;
	for (list<wstring>::const_iterator iter=filesList.begin(); iter!=filesList.end(); iter++)
	{
		INT64 size = FilesRefactorUtils::GetFileSize(*iter);

		if (size == 0)
		{
			if (FilesRefactorUtils::checkFileOpen(*iter))
			{
				wcout << L"FilesRefactor::DeleteZeroFiles: File In Use!" << endl;
				continue;
			}

			wcout << L"FilesRefactor::DeleteZeroFiles: Deleting file: ";
			FilesRefactorUtils::PrintUTF16ToStream(*iter, true, wcout);
			DeleteFileOperation dfo(m_parent, (*iter).c_str(), false, false, true);
			if (!dfo.Execute())
			{
				wcout << L"FilesRefactor::DeleteZeroFiles: Can't open file." << endl;

				FilesRefactorUtils::FillResponse(res, FAIL_UNEXPECTED_ERROR, DELETE_ZERO, L"An unexpected error occured.", 0, filesList.size());
				return;
			}

			deleted++;
		}

		ReportProgress((int)(progress+=interval), false);
	}

	FilesRefactorUtils::FillResponse(res, SUCCESS, DELETE_ZERO, L"", filesList.size(), 0);
}

/************************************/
/* Rename Methods					*/
/************************************/

void FilesRefactor::RenameFilesFindReplace(FRRESPONSE& res, std::list<wstring> &filesList, 
										   const std::wstring &search, const std::wstring &replace)
{
	FilesRenamerFindReplace rffr(m_parent, filesList, search, replace);
	rffr.Rename(res);
}

void FilesRefactor::RenameFilesAutoNumbering(FRRESPONSE& res, std::list<wstring> &filesList, int start)
{
	FilesRenamerAutonumbering fran(m_parent, filesList, start);
	fran.Rename(res);
}

void FilesRefactor::RenameFilesAlphabetize(FRRESPONSE& res, list<wstring>& filesList, bool start)
{
	if (start)
	{
		UnHideFile(res, filesList.front());
		return;
	}

	FilesRenamerAlphabetize fralpha(m_parent, filesList);
	fralpha.Rename(res);
}

void FilesRefactor::RenameFilesAppend(FRRESPONSE& res, std::list<wstring> &filesList, const std::wstring &prefix, 
									  const std::wstring &postfix)
{
	FilesRenamerAppend fra(m_parent, filesList, prefix, postfix);
	fra.Rename(res);
}

void FilesRefactor::RenameFilesAlphabetizeAppend(FRRESPONSE& res, std::list<wstring> &filesList, const std::wstring &prefix, 
												 const std::wstring &postfix)
{
	FilesRenamerAlphabetizeAppend fralphaa(m_parent, filesList, prefix, postfix);
	fralphaa.Rename(res);
}

void FilesRefactor::RenameFilesAutoNumberingAppend(FRRESPONSE& res, std::list<wstring> &filesList, int start, const wstring &prefix, const wstring &postfix)
{
	FilesRenamerAutonumberAppend fraa(m_parent, filesList, start, prefix, postfix);
	fraa.Rename(res);
}

void FilesRefactor::RenameFilesMakeSameName(FRRESPONSE& res, std::list<wstring> &filesList, const wstring &anchor)
{
	FilesRenamerMakeSameName frmsn(m_parent, filesList, anchor);
	frmsn.Rename(res);

	res.NewFiles.push_back(anchor);
}

void FilesRefactor::RenameFilesTruncate(FRRESPONSE& res, list<wstring>& filesList, int numberOfChars, bool truncFromBegining, bool includeFileExtension)
{
	FilesRenamerTruncate frt(m_parent, filesList, numberOfChars, truncFromBegining, includeFileExtension);
	frt.Rename(res);
}

bool FilesRefactor::CheckFilesSameName(FRRESPONSE &res, const list<wstring> &filesList)
{
	FileMachine fm(m_parent, wstring(filesList.front()));
	wstring checkName;
	fm.NameNoExt(checkName);
	for(list<wstring>::const_iterator iter=filesList.begin(); iter!=filesList.end(); iter++)
	{
		FileMachine fm1(m_parent, wstring(*iter));
		wstring fname;
		fm1.NameNoExt(fname);

		if (fname!=checkName)
		{
			return false;
		}
	}

	return true;
}

/************************************/
/* Split & Join Methods				*/
/************************************/

void FilesRefactor::SplitFile(FRRESPONSE& res, const std::wstring &file, size_t size)
{
	FileMachine fm(m_parent, file);
	if (!fm.IsFile())
	{
		wcout << L"FilesRefactor::SplitFile: a folder selected" << endl;

		FilesRefactorUtils::FillResponse(res, FAIL_IS_DIR_NOT_FILE, SPLIT, L"You can't split a folder.", 0, 1);
		return;
	}

	float progress = 1;
	ReportProgress((int)progress, false);

	size_t fileSize = (size_t)FilesRefactorUtils::GetFileSize(file);
	if (fileSize <= size)
	{
		wcout << L"FilesRefactor::SplitFile: wrong split size" << endl;

		FilesRefactorUtils::FillResponse(res, FAIL_WRONG_SPLIT_SIZE, SPLIT, L"Your file size is smaller or equal to the split size.", 0, 1);
		return;
	}

	const int chunk = 4096;

	int cFiles = (fileSize / size) + 1;
	WCHAR filesstr[10];
	_itow_s(cFiles, filesstr, 10, 10);
	wstring msg(wstring(filesstr) + L" files will be created.\nDo you want to split?");

	ReportProgress((int)progress++, true);

	if (FilesRefactorUtils::FrogMessageBox(m_parent, msg.c_str(), L"Split File", MB_YESNO|MB_ICONQUESTION)
		== IDNO)
	{
		wcout << L"FilesRefactor::SplitFile: User stopped operation" << endl;

		FilesRefactorUtils::FillResponse(res, FAIL_USER_DECIDED, SPLIT, L"", 0, 1);
		return;
	}

	ReportProgress((int)progress, false);

	FILE* pfile;
	_wfopen_s(&pfile, file.c_str(), L"r+b");

	if (pfile == NULL)
	{
		wcout << L"FilesRefactor::SplitFile: Can't open file." << endl;

		FilesRefactorUtils::FillResponse(res, FAIL_UNEXPECTED_ERROR, SPLIT, L"An unexpected error occured.", 0, 1);
		return;
	}

	float interval = (((float)100-(float)progress) / (float)cFiles);
	int count = 0;
	list<wstring> newFiles;
	while(!feof(pfile))
	{

		WCHAR numstr[10];
		_itow_s(count, numstr, 10, 10);
		wstring ext(L"." + wstring(SPLIT_EXTENSION));
		ext += numstr;

		wstring newFName(file + ext);

		FILE* outFile;
		_wfopen_s(&outFile, newFName.c_str(), L"w+b");

		int total = 0;

		if (count == 0)
		{
			WCHAR cfStr[10];
			_itow_s(cFiles, cfStr, 10, 10);
			fwrite(cfStr, 1, 10, outFile);
			total = 10;
		}

		WCHAR buffer[chunk];
		memset(buffer, 0, sizeof(buffer));

		while((total < size) && (!feof(pfile)))
		{
			int totake = min(chunk, size-total);
			size_t bytesread=fread(buffer, 1, totake, pfile);
			fwrite(buffer, 1, bytesread, outFile);
			total+=totake;
		}

		fclose(outFile);
		count++;
		newFiles.push_back(newFName);
		ReportProgress((int)(progress+=interval), false);
	}

	fclose(pfile);

	FilesRefactorUtils::FillResponse(res, SUCCESS, SPLIT, L"", 1, 0);
	res.NewFiles = newFiles;
}

void FilesRefactor::JoinFiles(FRRESPONSE& res, std::list<wstring> &filesList, bool flexible)
{
	if (flexible)
	{
		FileMachine fm(m_parent, filesList.front());
		int count = fm.GetLineCount(filesList.front());

		FilesRefactorUtils::FillResponse(res, FAIL_COUNT, JOIN, L"", count, 0);
		return;
	}

	const int chunk = 4096;

	float progress = 1;
	ReportProgress((int)progress, false);

	list<wstring> li(filesList);
	FilesRefactorUtils::CheckSortListFilesForJoin(res, li);
	if (res.Kind != SUCCESS) return;

	wstring filePath;
	FilesRefactorUtils::GetFilePathNoExt(filePath, li.front());

	FILE* cfile;
	_wfopen_s(&cfile, li.front().c_str(), L"r+b");

	WCHAR cFilesStr[10];
	fread(cFilesStr, 1, 10, cfile);
	fclose(cfile);
	int cFiles = _wtoi(cFilesStr);
	if (cFiles != (int)(li.size()))
	{
		wcout << L"FilesRefactor::JoinFiles: Missing some files to complete join. FAIL_WRONG_NUM_OF_FILES" << endl;

		FilesRefactorUtils::FillResponse(res, FAIL_WRONG_NUM_OF_FILES, JOIN, L"Missing files with in selection for Join.", 0, filesList.size());
		return;
	}

	ReportProgress((int)(progress+=2), false);

	FILE* outFile;
	_wfopen_s(&outFile, filePath.c_str(), L"w+b");

	list<wstring> newFiles;
	newFiles.push_back(filePath);

	int bufSize = (int)FilesRefactorUtils::GetFileSize(li.front());
	int size = li.size();
	float interval = (((float)100-(float)progress) / (float)size);
	for (int i=0; i<size-1; i++)
	{
		FILE* pfile;
		_wfopen_s(&pfile, li.front().c_str(), L"r+b");

		if (pfile == NULL)
		{
			wcout << L"FilesRefactor::JoinFiles: Can't open file." << endl;
			fclose(outFile);

			FilesRefactorUtils::FillResponse(res, FAIL_UNEXPECTED_ERROR, JOIN, L"An unexpected error occured.", 0, filesList.size());
			return;
		}

		WCHAR buffer[chunk];
		int total = 0;
		if (i==0)
		{
			total = 10;
			fread(buffer, 1, 10, pfile);
		}

		memset(buffer, 0, sizeof(buffer));

		while(total < bufSize)
		{
			int totake = min(chunk, bufSize-total);
			size_t bytesread=fread(buffer, 1, totake, pfile);
			fwrite(buffer, 1, bytesread, outFile);
			total+=totake;
		}

		li.pop_front();
		fclose(pfile);
		ReportProgress((int)(progress+=2), false);

		ReportProgress((int)(progress+=interval), false);
	}

	bufSize = (int)FilesRefactorUtils::GetFileSize(li.back());

	FILE* pfile;
	_wfopen_s(&pfile, li.back().c_str(), L"r+b");
	if (pfile == NULL)
	{
		wcout << L"FilesRefactor::JoinFiles: Can't open file." << endl;
		fclose(outFile);

		FilesRefactorUtils::FillResponse(res, FAIL_UNEXPECTED_ERROR, JOIN, L"An unexpected error occured.", 0, filesList.size());
		return;
	}

	WCHAR buffer[chunk];

	int total = 0;
	while(total < bufSize)
	{
		int totake = min(chunk, bufSize-total);
		size_t bytesread=fread(buffer, 1, totake, pfile);
		fwrite(buffer, 1, bytesread, outFile);
		total+=totake;
	}

	ReportProgress((int)(progress+=interval), false);

	fclose(pfile);
	fclose(outFile);

	FilesRefactorUtils::FillResponse(res, SUCCESS, JOIN, L"", filesList.size(), 0);
	res.NewFiles = newFiles;
}


/************************************/
/* Image Resize Methods				*/
/************************************/

void FilesRefactor::ShrinkImageFilesByPercent(FRRESPONSE& res, std::list<wstring> &filesList, double shrinkBy, int quality, bool saveJPG, const wstring& wrapFolder)
{
	float progress = 1;
	ReportProgress((int)progress, false);

	GdiplusStartupInput gdiplusStartupInput;
	ULONG_PTR  gdiplusToken;
	GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

	float interval = ((float)(100-progress) / (float)(filesList.size()));
	int failed = 0;
	list<wstring> newFiles;

	if (wrapFolder != wstring(L""))
	{
		FileMachine fm(m_parent, filesList.front());
		wstring tmpfolder;
		fm.Folder(tmpfolder);
		newFiles.push_back(tmpfolder + L"\\" + wrapFolder);
	}

	for(list<wstring>::const_iterator iter = filesList.begin(); iter != filesList.end(); iter++)
	{
		Image image((*iter).c_str());
		int width = image.GetWidth();
		int height = image.GetHeight();

		WCHAR byStr[8];
		_itow_s((int)(shrinkBy*100), byStr, 8, 10);
		wstring bywstr(byStr);

		wstring qwstr(L"");
		if(quality >-1)
		{
			WCHAR qStr[8];
			_itow_s(quality, qStr, 8, 10);
			qwstr = L"Q";
			qwstr.append(qStr);
		}

		wstring postFix(L"_FrogResizer" + bywstr + L"%" + qwstr);

		FileResizer fres(m_parent, (int)(width*shrinkBy), (int)(height*shrinkBy));
		if(fres.Resize((*iter).c_str(), quality, postFix, saveJPG, newFiles, wrapFolder) == RESIZERFAIL)
		{
			failed++;
		}

		ReportProgress((int)(progress+=interval), false);
	}

	GdiplusShutdown(gdiplusToken);

	if (failed > 0)
	{
		WCHAR str[10];
		_itow_s(failed, str, 10, 10);
		wstring msg(str + wstring(L" files or folders failed to resize.\nProbably not an image file or the image type isn't supported."));

		FilesRefactorUtils::FillResponse(res, FAIL_SOME_FILES_FAILED, RESIZE_IMAGE, msg.c_str(), (filesList.size() - failed), failed);
	}
	else
	{
		FilesRefactorUtils::FillResponse(res, SUCCESS, RESIZE_IMAGE, L"", filesList.size(), 0);
	}

	res.NewFiles = newFiles;
}

void FilesRefactor::ShrinkImageFilesBySize(FRRESPONSE& res, std::list<wstring> &filesList, int width, int height, int quality, bool saveJPG, const wstring& wrapFolder)
{
	float progress = 1;
	ReportProgress((int)progress, false);

	float interval = ((float)(100-progress) / (float)(filesList.size()));
	int failed = 0;
	list<wstring> newFiles;

	if (wrapFolder != wstring(L""))
	{
		FileMachine fm(m_parent, filesList.front());
		wstring tmpfolder;
		fm.Folder(tmpfolder);
		newFiles.push_back(tmpfolder + L"\\" + wrapFolder);
	}

	for(list<wstring>::const_iterator iter = filesList.begin(); iter != filesList.end(); iter++)
	{
		WCHAR widthStr[8];
		_itow_s(width, widthStr, 8, 10);
		wstring widthwstr(widthStr);
		WCHAR heightStr[8];
		_itow_s(height, heightStr, 8, 10);
		wstring heightwstr(heightStr);

		wstring qwstr(L"");
		if(quality >-1)
		{
			WCHAR qStr[8];
			_itow_s(quality, qStr, 8, 10);
			qwstr = L"Q";
			qwstr.append(qStr);
		}

		wstring postFix(L"_FrogResizer" + widthwstr + L"x" + heightwstr + qwstr);

		FileResizer fres(m_parent, width, height);

		if (fres.Resize((*iter).c_str(), quality, postFix, saveJPG, newFiles, wrapFolder) == RESIZERFAIL)
		{
			failed ++;
		}

		ReportProgress((int)(progress+=interval), false);
	}

	if (failed > 0)
	{
		WCHAR str[10];
		_itow_s(failed, str, 10, 10);
		wstring msg(str + wstring(L" files or folders failed to resize.\nProbably not an image file or the image type isn't supported."));

		FilesRefactorUtils::FillResponse(res, FAIL_SOME_FILES_FAILED, RESIZE_IMAGE, msg.c_str(), (filesList.size() - failed), failed);
	}
	else
		FilesRefactorUtils::FillResponse(res, SUCCESS, RESIZE_IMAGE, L"", filesList.size(), 0);
	res.NewFiles = newFiles;
}

/************************************/
/* Encryption Methods				*/
/************************************/

void FilesRefactor::EncryptList(FRRESPONSE& res, std::list<wstring> &filesList,  const wstring& password, 
								float progress, float pInterval)
{
	int success = 0;
	for(list<wstring>::const_iterator iter = filesList.begin(); iter != filesList.end(); iter++)
	{
		wstring destStr((*iter) + L"." + ENCRYPTION_EXTENSION);
		if (PathFileExists(destStr.c_str()))
		{
			wstring msg(L"The file or directory : " + *iter + L"Already exist in its encrypted version.\nDo you want to overwrite?\n(Be careful... this might be a directory and its content will be delivered to the recycle bin)");

			int ans = FilesRefactorUtils::FrogMessageBox(m_parent, msg.c_str(), L"Encrypt File Exist", MB_YESNOCANCEL|MB_ICONQUESTION);
			if (ans == IDCANCEL)
			{
				wcout << L"FilesRefactor::EncryptList: User stopped operation" << endl;

				FilesRefactorUtils::FillResponse(res, FAIL_USER_DECIDED, ENCRYPT, L"", 0, filesList.size());
				return;
			}
			if (ans == IDNO)
			{
				continue;
			}

			DeleteFileOperation dfo(m_parent, destStr.c_str(), false, true, true);
			dfo.Execute();
		}
		wcout << L"FilesRefactor::EncryptList: Encrypting : ";
		FilesRefactorUtils::PrintUTF16ToStream(*iter, true, wcout);
		PRIVRESPONSE pres = FilePrivacy::RC4EncryptFile(m_parent, (*iter).c_str(), password.c_str());
		if (pres != SUCCESS_PRIV)
		{
			if (pres == FAIL_ENC_DIR)
			{
				list<wstring> innerFiles;
				FilesRefactorUtils::MakeListInDir(*iter, innerFiles);

				FRRESPONSE resp;
				EncryptList(resp, innerFiles, password, progress, pInterval);

				if (resp.Kind != SUCCESS)
				{
					res = resp;
					return;
				}
			}
			else
			{
				WCHAR resstr[10];
				_itow_s((int)pres, resstr, 10, 10);
				wstring msg(L"Can't encrypt file: " + *iter + L".\n\nError: PRIVRESPONSE " + wstring(resstr));
				ReportProgress((int)progress, true);
				FilesRefactorUtils::FrogMessageBox(m_parent, msg.c_str(), L"Can't Encrypt!!!", MB_OK|MB_ICONERROR);
				ReportProgress((int)(progress+=pInterval), false);
				continue;
			}
		}

		RenameFileOperation rfo(m_parent, (*iter).c_str(), destStr.c_str(), false, false);
		if (!rfo.Execute())
		{
			wcout << L"FilesRefactor::EncryptList: Unexpected error RenameFileOperation.execute()!";

			FilesRefactorUtils::FillResponse(res, FAIL_UNEXPECTED_ERROR, ENCRYPT, L"An unexpected error occured.", 0, filesList.size());
			return;
		}

		success++;
		ReportProgress((int)(progress+=pInterval), false);
	}
	if (success == (int)filesList.size())
		FilesRefactorUtils::FillResponse(res, SUCCESS, ENCRYPT, L"", success, 0);
	else
	{
		WCHAR str[10];
		_itow_s((filesList.size() - success), str, 10, 10);
		wstring msg(str + wstring(L" files or folders failed to encrypt."));

		FilesRefactorUtils::FillResponse(res, FAIL_SOME_FILES_FAILED, ENCRYPT, msg.c_str(), success, (filesList.size() - success));
	}
}

void FilesRefactor::Encrypt(FRRESPONSE& res, std::list<wstring> &filesList, const wstring& password, bool deleteFile)
{
	float progress = 1;
	ReportProgress((int)progress, true);



	wstring msg(L"The selected files will be encrypted with the given password.\nYou must make sure you remember this password since this operation is irreversible without it.\nDo you want to continue?");
	if (FilesRefactorUtils::FrogMessageBox(m_parent, msg.c_str(), L"Encrypt File Warning", MB_YESNO|MB_ICONWARNING)
		== IDNO)
	{
		wcout << L"FilesRefactor::EncryptList: User stopped operation" << endl;

		FilesRefactorUtils::FillResponse(res, FAIL_USER_DECIDED, ENCRYPT, L"", 0, filesList.size());
		return;
	}

	ReportProgress((int)progress, false);

	// checking if some of the files are open and if yes they are taken out of the list.
	bool somefail = false;
	list<wstring> tmpList;
	for(list<wstring>::const_iterator iter = filesList.begin(); iter != filesList.end(); iter++)
	{
		if (FilesRefactorUtils::checkFileOpen(*iter))
		{
			somefail = true;
		}
		else
		{
			tmpList.push_back(*iter);
		}
	}
	int total = filesList.size();
	int rest = tmpList.size();
	filesList = tmpList;


	wstring tmp(L"");
	list<wstring> bckpList;
	FileMachine fm(m_parent, filesList.front().c_str());
	wstring folder;
	fm.Folder(folder);
	if (!deleteFile) // copying all files before starting - for backup
	{
		if (!FilesRefactorUtils::GetTempFile(folder, tmp))
		{
			wcout << L"FilesRefactor::Encrypt: get temp file failed" << endl;

			FilesRefactorUtils::FillResponse(res, FAIL_UNEXPECTED_ERROR, ENCRYPT, L"An unexpected error occured.", 0, filesList.size());
			return;
		}

		DeleteFileOperation dfo(m_parent, tmp.c_str(), false, true, false);
		if (!dfo.Execute())
		{
			wcout << L"FilesRefactor::Encrypt: DeleteFileOperation failed" << endl;

			FilesRefactorUtils::FillResponse(res, FAIL_UNEXPECTED_ERROR, ENCRYPT, L"An unexpected error occured.", 0, filesList.size());
			return;
		}

		if (!CreateDirectory(tmp.c_str(), NULL)) 
		{ 
			wcout << L"FilesRefactor::Encrypt: CreateDirectory failed (%d)" << GetLastError() << endl;

			FilesRefactorUtils::FillResponse(res, FAIL_UNEXPECTED_ERROR, ENCRYPT, L"An unexpected error occured.", 0, filesList.size());
			return;
		}

		for(list<wstring>::const_iterator iter = filesList.begin(); iter != filesList.end(); iter++)
		{
			FileMachine fm(m_parent, iter->c_str());
			wstring fileName;
			fm.NamePlusExt(fileName);
			wstring dest(tmp + L"\\" + fileName);
			CopyFileOperation cfo(m_parent, iter->c_str(), dest.c_str(), false, true);
			if (!cfo.Execute())
			{
				wcout << L"FilesRefactor::Encrypt: CopyFileOperation failed" << endl;

				FilesRefactorUtils::FillResponse(res, FAIL_UNEXPECTED_ERROR, ENCRYPT, L"An unexpected error occured.", 0, filesList.size());
				return;
			}

			bckpList.push_back(dest);
		}
	}

	int totalFiles = FilesRefactorUtils::CalcTotalFiles(m_parent, filesList, 0);
	float interval = ((float)((float)100-progress) / (float)(totalFiles));

	EncryptList(res, filesList, password, progress, interval); // the last time res is changed is here ...

	// if some files are open prepare the right answer.
	if ((somefail) && (res.Kind != FAIL_UNEXPECTED_ERROR) && (res.Kind != FAIL_USER_DECIDED))
	{
		WCHAR str[10];
		_itow_s((total-rest) + res.NumOfFailed, str, 10, 10);
		wstring msg(str + wstring(L" files or folders failed to encrypt."));

		FilesRefactorUtils::FillResponse(res, FAIL_SOME_FILES_FAILED, ENCRYPT, L"", res.NumOfSucceeded, (total-rest) + res.NumOfFailed);
	}

	if (!deleteFile)
	{
		for(list<wstring>::const_iterator iter = bckpList.begin(); iter != bckpList.end(); iter++)
		{
			FileMachine fm1(m_parent, *iter);
			wstring fileName;
			fm1.NamePlusExt(fileName);
			wstring dest(folder + L"\\" + fileName);
			MoveFileOperation mfo(m_parent, iter->c_str(), dest.c_str(), false, true);
			if (!mfo.Execute())
			{
				wcout << L"FilesRefactor::Encrypt: MoveFileOperation failed" << endl;

				FilesRefactorUtils::FillResponse(res, FAIL_UNEXPECTED_ERROR, ENCRYPT, L"An unexpected error occured.", 0, filesList.size());
				return;
			}
		}

		DeleteFileOperation dfo(m_parent, tmp.c_str(), false, true, false);
		if (!dfo.Execute())
		{
			wcout << L"FilesRefactor::Encrypt: DeleteFileOperation failed" << endl;

			FilesRefactorUtils::FillResponse(res, FAIL_UNEXPECTED_ERROR, ENCRYPT, L"An unexpected error occured.", 0, filesList.size());
			return;
		}
	}
}

/************************************/
/* Decryption Methods				*/
/************************************/

void FilesRefactor::DecryptList(FRRESPONSE& res, std::list<wstring> &filesList, const wstring& password, 
								float progress, float pInterval)
{
	int success = 0;
	for(list<wstring>::const_iterator iter = filesList.begin(); iter != filesList.end(); iter++)
	{
		if (!PathFileExists(iter->c_str()))
		{
			wcout << L"DecryptList: File doesn't exist: ";
			FilesRefactorUtils::PrintUTF16ToStream(*iter, true, wcout);
			continue;
		}

		FileMachine fm(m_parent, *iter);
		wstring ext;
		fm.Extension(ext);
		if(ext != ENCRYPTION_EXTENSION)
		{
			ReportProgress((int)progress, true);
			wcout << "No enc extention for: ";
			FilesRefactorUtils::PrintUTF16ToStream(*iter, true, wcout);
			//wstring msg(L"Can't decrypt!\nFile: " + *iter + L" is not encrypted.");
			//MessageBox(m_parent, msg.c_str(), L"Can't Decrypt", MB_OK|MB_ICONERROR);
		}
		else
		{
			//wstring tmpext(ENCRYPTION_EXTENSION);
			wstring destStr((*iter).substr(0, (*iter).length()-wcslen(ENCRYPTION_EXTENSION)));
			if (fm.IsFile())
			{
				if (FilePrivacy::CheckPassword((*iter).c_str(), password.c_str()))
				{

					if (PathFileExists(destStr.c_str()))
					{
						wstring msg(L"The file or directory : " + *iter + L" Already exist in its decrypted version.\nDo you want to overwrite?\n(Be careful... this might be a directory and its content will be delivered to the recycle bin)");

						int ans = FilesRefactorUtils::FrogMessageBox(m_parent, msg.c_str(), L"Decrypt File Exist", MB_YESNOCANCEL|MB_ICONQUESTION);
						if (ans == IDCANCEL)
						{
							wcout << L"FilesRefactor::DecryptList: User stopped operation" << endl;

							FilesRefactorUtils::FillResponse(res, FAIL_USER_DECIDED, DECRYPT, L"", success, filesList.size() - success);
							return;
						}
						if (ans == IDNO)
						{
							continue;
						}

						DeleteFileOperation dfo(m_parent, destStr.c_str(), false, true, true);
						if (!dfo.Execute())
						{
							wcout << L"FilesRefactor::DecryptList: DeleteFileOperation failed" << endl;

							FilesRefactorUtils::FillResponse(res, FAIL_UNEXPECTED_ERROR, DECRYPT, L"An unexpected error occured.", 0, filesList.size());
							return;
						}
					}

					PRIVRESPONSE pres = FilePrivacy::RC4DecryptFile(m_parent, (*iter).c_str(), password.c_str());
					if (pres != SUCCESS_PRIV)
					{
						WCHAR resstr[10];
						_itow_s((int)pres, resstr, 10, 10);

						ReportProgress((int)progress, true);
						wstring msg(L"Can't decrypt file: " + *iter + L".\n\nError: PRIVRESPONSE " + wstring(resstr));
						FilesRefactorUtils::FrogMessageBox(m_parent, msg.c_str(), L"Can't Decrypt", MB_OK|MB_ICONERROR);
						ReportProgress((int)(progress+=pInterval), false);
						continue;
					}

					RenameFileOperation rfo(m_parent, (*iter).c_str(), destStr.c_str(), true, false);
					if (!rfo.Execute())
					{
						wcout << L"FilesRefactor::DecryptList: RenameFileOperation failed" << endl;

						FilesRefactorUtils::FillResponse(res, FAIL_UNEXPECTED_ERROR, DECRYPT, L"An unexpected error occured.", 0, filesList.size());
						return;
					}

					success++;
				}
				else
				{
					ReportProgress((int)progress, true);
					wcout << "Wrong Password!" << endl;
					wstring msg(L"Wrong password for file: " + *iter + L".");
					FilesRefactorUtils::FrogMessageBox(m_parent, msg.c_str(), L"Wrong Password", MB_OK|MB_ICONERROR);

					FilesRefactorUtils::FillResponse(res, FAIL_WRONG_PASSWORD, DECRYPT, msg.c_str(), success, filesList.size()-success);
				}
			}
			else
			{
				if (PathFileExists(destStr.c_str()))
				{
					wstring msg(L"The file or directory : " + *iter + L"Already exist in its decrypted version.\nDo you want to overwrite?\n(Be careful... this might be a directory and its content will be delivered to the recycle bin)");

					int ans = FilesRefactorUtils::FrogMessageBox(m_parent, msg.c_str(), L"Decrypt File Exist", MB_YESNOCANCEL|MB_ICONQUESTION);
					if (ans == IDCANCEL)
					{
						wcout << L"FilesRefactor::DecryptList: User stopped operation" << endl;

						FilesRefactorUtils::FillResponse(res, FAIL_USER_DECIDED, DECRYPT, L"", success, filesList.size() - success);
						return;
					}
					if (ans == IDNO)
					{
						continue;
					}

					DeleteFileOperation dfo(m_parent, destStr.c_str(), false, true, true);
					if (!dfo.Execute())
					{
						wcout << L"FilesRefactor::DecryptList: DeleteFileOperation failed" << endl;

						FilesRefactorUtils::FillResponse(res, FAIL_UNEXPECTED_ERROR, DECRYPT, L"An unexpected error occured.", 0, filesList.size());
						return;
					}
				}

				list<wstring> innerFiles;
				FilesRefactorUtils::MakeListInDir(*iter, innerFiles);

				FRRESPONSE respon;
				DecryptList(respon, innerFiles, password, progress, pInterval);

				if ((respon.Kind == FAIL_USER_DECIDED) || (respon.Kind == FAIL_UNEXPECTED_ERROR))
				{
					res = respon;
					return;
				}

				if (respon.Kind == FAIL_WRONG_PASSWORD)
				{
					res.Kind = respon.Kind;
					continue;
				}

				RenameFileOperation rfo(m_parent, (*iter).c_str(), destStr.c_str(), false, false);
				if (!rfo.Execute())
				{
					wcout << L"FilesRefactor::DecryptList: DeleteFileOperation failed" << endl;

					FilesRefactorUtils::FillResponse(res, FAIL_UNEXPECTED_ERROR, DECRYPT, L"An unexpected error occured.", 0, filesList.size());
					return;
				}

				success++;
			}
		}

		ReportProgress((int)(progress+=pInterval), false);
	}

	if (success == (int)filesList.size())
		FilesRefactorUtils::FillResponse(res, SUCCESS, DECRYPT, L"", success, 0);
}

void FilesRefactor::Decrypt(FRRESPONSE& res, std::list<wstring> &filesList, const wstring& password)
{
	float progress = 1;
	ReportProgress((int)progress, false);

	int totalFiles = FilesRefactorUtils::CalcTotalFiles(m_parent, filesList, 0);
	float interval = ((float)((float)100-progress) / (float)(totalFiles));

	DecryptList(res, filesList, password, progress, interval);
}

/************************************/
/* PDF Methods						*/
/************************************/

void FilesRefactor::GeneratePdf(FRRESPONSE& res, PDFFile& pdfFile, bool pagesFlat)
{
	PDFCreator pdfc(m_parent);
	if (pagesFlat)
	{
		res.Kind = FAIL_PDF_FAIL;
		if (pdfc.CheckValidPDF(pdfFile.FilePath))
			res.NumOfSucceeded = 1;
		else
			res.NumOfSucceeded = 0;
	}
	else
	{
		pdfc.Go(pdfFile);

		list<wstring> newFiles;
		newFiles.push_back(pdfFile.FilePath);

		FilesRefactorUtils::FillResponse(res, SUCCESS, PDF_ALBUM, L"", 1, 0);
		res.NewFiles = newFiles;
	}
}

// The magic function which does all the touching

void FilesRefactor::TouchFiles(FRRESPONSE& res, const list<wstring>& filesList)
{
	SYSTEMTIME now;
	FILETIME tsUserTime;
	FILETIME  tsATime;
	FILETIME  tsMTime;
	FILETIME  tsCTime;

	GetSystemTime(&now);

	if (!SystemTimeToFileTime(&now, &tsUserTime))
	{
		FilesRefactorUtils::FillResponse(res, FAIL_UNEXPECTED_ERROR, TOUCH_FILES, L"Unexpected error occured on SystemTimeToFileTime()", 0, filesList.size());
		return;
	}

	tsATime = tsMTime = tsCTime = tsUserTime;

	// Touch all of the files
	for (list<wstring>::const_iterator iter = filesList.begin(); iter != filesList.end(); iter++)
	{
		FilesRefactorUtils::Touch(iter->c_str(), &tsATime, &tsMTime, &tsCTime);
	}
	FilesRefactorUtils::FillResponse(res, SUCCESS, TOUCH_FILES, L"", filesList.size(), 0);
}

void FilesRefactor::LogoOnImages(FRRESPONSE& res, const list<wstring>& filesList, const wstring& logoPath,
								 const wstring& logoText, LOGFONTW logoFont, Gdiplus::Color fontColor,
								 bool addBorder, Gdiplus::Color borderColor, 
								 bool useLogoImage, IMAGE_LOC location, const wstring& wrapFolder)
{
	GdiplusStartupInput gdiplusStartupInput;
	ULONG_PTR  gdiplusToken;
	list<wstring> newFiles;
	int failed = 0;

	if (wrapFolder != wstring(L""))
	{
		FileMachine fm(m_parent, filesList.front());
		wstring tmpfolder;
		fm.Folder(tmpfolder);
		newFiles.push_back(tmpfolder + L"\\" + wrapFolder);
	}

	GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

	Image* logoImage = NULL;
	Font* textFont = NULL;
	
	int lwidth = 0;
	int lheight = 0;

	if (useLogoImage)
	{
		logoImage = new Image(logoPath.c_str());

		lwidth = logoImage->GetWidth();
	    lheight = logoImage->GetHeight();
	}

	for(list<wstring>::const_iterator iter = filesList.begin(); iter != filesList.end(); iter++)
	{
		Image image((*iter).c_str());
		
		int width = image.GetWidth();
		int height = image.GetHeight();

		if (useLogoImage && (width < lwidth) || (height < lheight))
		{
			failed++;
			continue;
		}

		Bitmap destBitmap(width, height);

		REAL locx;
		REAL locy;
		wstring locstr;

		Graphics graphics(&destBitmap);
		graphics.SetSmoothingMode(SmoothingModeHighQuality);
		graphics.SetInterpolationMode(InterpolationModeHighQualityBicubic);
		graphics.SetPixelOffsetMode(PixelOffsetModeHighQuality);
		graphics.SetTextRenderingHint(TextRenderingHintAntiAlias);

		int textOffset = 0;

		if (addBorder)
		{		
			int borderW = 20;
			int borderH = 20;			

			int border = 10;

			textOffset = borderW;

			int newW = width - 2*borderW;
			int newH = height - 2*borderH;

			Gdiplus::SolidBrush whiteBrush(Color::White);
			graphics.FillRectangle(&whiteBrush, 0, 0, width, height);

			int shade = border;
			int shadeOffset = (border / 2) + 3;

			for (int i = shade; i>0; i--)
			{
				unsigned char alpha = 180;
				
				int fadeStart = shade / 2;

				if (fadeStart < 3)
				{
					fadeStart = 3;
				}

				if (i > fadeStart)
				{
					int factor = 180 / (shade - fadeStart);
					alpha -= factor * (i - fadeStart);
				}

				unsigned char grayLevel =  alpha / 10;
				Gdiplus::Color shadeColor(alpha , grayLevel, grayLevel, grayLevel);
				Gdiplus::SolidBrush shadeBrush(shadeColor);

				int shadeW = newW + (border*2) + 2 * (i - shade);
				int shadeH = newH + (border*2) + 2 * (i - shade);

				int shadeX = borderW - border + shadeOffset + shade - i;
				int shadeY = borderH - border + shadeOffset + shade - i;

				graphics.FillRectangle(&shadeBrush, shadeX, shadeY, shadeW, shadeH);
			}

			Gdiplus::SolidBrush borderBrush(borderColor);
			graphics.FillRectangle(&borderBrush, borderW - border, borderH - border, newW + (border*2), newH + (border*2));

			RectF rect(borderW, borderH, newW, newH);
			graphics.DrawImage(&image, rect);
		}
		else
		{
			RectF rect(0, 0, (REAL)width, (REAL)height);
			graphics.DrawImage(&image, rect, 0, 0, (REAL)width, (REAL)height, UnitPixel);			
		}

		if (!useLogoImage)
		{
			HDC hDDC = GetDC(GetDesktopWindow());
			textFont = new Gdiplus::Font(hDDC, &logoFont);

			if (textFont->GetLastStatus() == Status::NotTrueTypeFont)
			{
				delete textFont;

				logoFont.lfCharSet = 177;
				logoFont.lfOutPrecision = 1;
				logoFont.lfClipPrecision = 2;
				logoFont.lfQuality = 1;
				wcscpy_s(logoFont.lfFaceName, LF_FACESIZE, L"Times new Roman");

				textFont = new Gdiplus::Font(hDDC, &logoFont);
			}
			
			RectF resultsRect;
			
			StringFormat format;
			format.SetAlignment(StringAlignmentNear);

			if (graphics.MeasureString(logoText.c_str(), -1, textFont, PointF(0,0), &format, &resultsRect) == Ok)
			{				
				lwidth = resultsRect.Width;
				lheight = resultsRect.Height;
			}
		}

		if (location == IMAGE_LOC::TOP_LEFT)
		{
			locx = 0;
			locy = 0;
			locstr = L"TL";
		}
		else if (location == IMAGE_LOC::TOP_CENTER)
		{
			locx = ((REAL)width/(REAL)2) - ((REAL)lwidth/(REAL)2);
			locy = 0;
			locstr = L"TC";
		}
		else if (location == IMAGE_LOC::TOP_RIGHT)
		{
			locx = width-lwidth;
			locy = 0;
			locstr = L"TR";
		}
		else if (location == IMAGE_LOC::MIDDLE_LEFT)
		{
			locx = 0;
			locy = ((REAL)height/(REAL)2) - ((REAL)lheight/(REAL)2);
			locstr = L"ML";
		}
		else if (location == IMAGE_LOC::MIDDLE_CENTER)
		{
			locx = ((REAL)width/(REAL)2) - ((REAL)lwidth/(REAL)2);
			locy = ((REAL)height/(REAL)2) - ((REAL)lheight/(REAL)2);
			locstr = L"MC";
		}
		else if (location == IMAGE_LOC::MIDDLE_RIGHT)
		{
			locx = width-lwidth;
			locy = ((REAL)height/(REAL)2) - ((REAL)lheight/(REAL)2);
			locstr = L"MR";
		}
		else if (location == IMAGE_LOC::BOTTOM_LEFT)
		{
			locx = 0;
			locy = height-lheight;
			locstr = L"BL";
		}
		else if (location == IMAGE_LOC::BOTTOM_CENTER)
		{
			locx = ((REAL)width/(REAL)2) - ((REAL)lwidth/(REAL)2);
			locy = height-lheight;
			locstr = L"BC";
		}
		else if (location == IMAGE_LOC::BOTTOM_RIGHT)
		{
			locx = width-lwidth;
			locy = height-lheight;
			locstr = L"BR";
		}

		if (locx == 0)
		{
			locx+= textOffset;
		}
		else
		{
			locx-= textOffset;
		}

		if (locy == 0)
		{
			locy+= textOffset;
		}
		else
		{
			locy-= textOffset;
		}

		if (useLogoImage)
		{
			RectF rectLogo(locx, locy, (REAL)lwidth, (REAL)lheight);
			graphics.DrawImage(logoImage, rectLogo, 0, 0, (REAL)lwidth, (REAL)lheight, UnitPixel);
		}
		else
		{
		
			Gdiplus::SolidBrush textBrush(Color::White);
			textBrush.SetColor(fontColor);

			RectF boundingRect;

			boundingRect.X = locx;
			boundingRect.Y = locy;
			boundingRect.Width = lwidth+1;
			boundingRect.Height = lheight+1;

			//Gdiplus::Pen pen(Color::Green);
			//graphics.DrawRectangle(&pen, boundingRect);		

			StringFormat format;
			format.SetAlignment(StringAlignmentNear);
			graphics.DrawString(logoText.c_str(), -1, textFont, boundingRect, &format, &textBrush);
		}
	
		wstring mimetype(L"image/jpeg");
	
		wstring destFile;
		FileMachine fm(m_parent, *iter);

		fm.MimeType(mimetype);

		CLSID clsid;
		FilesRefactorUtils::GetEncoderCLSID(mimetype.c_str(), &clsid);

		if (wrapFolder == wstring(L""))
		{
			wstring namenoext;
			wstring ext;
			fm.PathPlusNameNoExt(namenoext);
			fm.Extension(ext);
			destFile = namenoext + wstring(L"_plus_logo_") + locstr + wstring(L".") + ext;
		}
		else
		{
			fm.Folder(destFile);
			destFile += L"\\" + wrapFolder;
			if (!PathFileExists(destFile.c_str()))
			{
				CreateDirectory(destFile.c_str(), NULL);
			}

			wstring fname;
			fm.NamePlusExt(fname);
			destFile += L"\\" + fname;
		}

		destBitmap.Save(destFile.c_str(), &clsid);

		if (wrapFolder == wstring(L""))
		{
			newFiles.push_back(destFile);
		}
	}

	if (logoImage)
	{
		delete logoImage;
		logoImage = NULL;
	}

	if (textFont)
	{
		delete textFont;
		textFont = NULL;
	}

	GdiplusShutdown(gdiplusToken);

	if (failed > 0)
	{
		WCHAR str[10];
		_itow_s(failed, str, 10, 10);
		wstring msg(wstring(L"failed to put the logo on") + str + wstring(L" files or folders."));

		FilesRefactorUtils::FillResponse(res, FAIL_SOME_FILES_FAILED, LOGO_ON_IMAGES, msg.c_str(), (filesList.size() - failed), failed);
	}
	else
	{
		FilesRefactorUtils::FillResponse(res, SUCCESS, LOGO_ON_IMAGES, L"", filesList.size(), 0);
	}

	res.NewFiles = newFiles;
}